CreateQueryLookupStrategy.java
package org.codefilarete.stalactite.spring.repository.query;
import java.lang.reflect.Method;
import org.codefilarete.stalactite.engine.runtime.AdvancedEntityPersister;
import org.codefilarete.stalactite.spring.repository.query.domain.PartTreeStalactiteDelete;
import org.codefilarete.stalactite.spring.repository.query.domain.PartTreeStalactiteQuery;
import org.codefilarete.stalactite.spring.repository.query.projection.PartTreeStalactiteCountProjection;
import org.codefilarete.stalactite.spring.repository.query.projection.PartTreeStalactiteExistsProjection;
import org.codefilarete.stalactite.spring.repository.query.projection.PartTreeStalactiteProjection;
import org.codefilarete.stalactite.sql.Dialect;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.parser.PartTree;
/**
* {@link QueryLookupStrategy} that creates a query for each candidate derived-query-method.
*
* @param <T>
* @author Guillaume Mary
*/
public class CreateQueryLookupStrategy<T> implements QueryLookupStrategy {
private final AdvancedEntityPersister<T, ?> entityPersister;
private final Dialect dialect;
public CreateQueryLookupStrategy(AdvancedEntityPersister<T, ?> entityPersister,
Dialect dialect) {
this.entityPersister = entityPersister;
this.dialect = dialect;
}
@Override
public RepositoryQuery resolveQuery(Method method,
RepositoryMetadata metadata,
ProjectionFactory factory,
NamedQueries namedQueries) {
PartTree partTree = new PartTree(method.getName(), entityPersister.getClassToPersist());
StalactiteQueryMethod queryMethod = new StalactiteQueryMethod(method, metadata, factory);
new QueryMethodValidator(partTree, queryMethod).validate();
if (partTree.isDelete()) {
return new PartTreeStalactiteDelete<>(queryMethod, entityPersister, partTree, dialect);
} else if (partTree.isCountProjection()) {
return new PartTreeStalactiteCountProjection<>(queryMethod, entityPersister, partTree);
} else if (partTree.isExistsProjection()) {
return new PartTreeStalactiteExistsProjection<>(queryMethod, entityPersister, partTree);
} else if ((queryMethod.getResultProcessor().getReturnedType().isProjecting()
&& factory.getProjectionInformation(queryMethod.getReturnedObjectType()).isClosed())
|| queryMethod.getParameters().hasDynamicProjection()
) {
// The projection is closed: it means there's not @Value on the interface, so we can use Spring property introspector to look up for
// properties to select in the query
// If the projection is open (any method as a @Value on it), then, because Spring can't know in advance which field will be required to
// evaluate the @Value expression, we must retrieve the whole aggregate as entities.
// se https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html
return new PartTreeStalactiteProjection<>(queryMethod, entityPersister, partTree, factory);
} else {
return new PartTreeStalactiteQuery<>(queryMethod, entityPersister, partTree);
}
}
}